package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.common.ResponseCode;
import com.itheima.stock.common.domain.*;
import com.itheima.stock.ex.CustomerException;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.OutputStream;
import java.util.*;

/**
 * @ClassName StockServiceImpl
 * @Description TODO
 * @Author Zack
 * @Date 2022/12/7 10:03
 * @Version 1.0
 */
@Service
@Slf4j
public class StockServiceImpl implements StockService {
    final String TIME_FORMAT_STR = "yyyy-MM-dd HH:mm:ss";
    @Autowired
    StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    StockInfoConfig stockInfoConfig;

    @Autowired
    StockBlockRtInfoMapper sbriMapper;

    @Autowired
    StockRtInfoMapper stockRtInfoMapper;

    @Value("${stock.excel-name}")
    String stockExcelFileName;

    @Override
    public R<List<InnerMarketDomain>> innerIndexAll() {
        List<String> innerIds = stockInfoConfig.getInner();
        //获取大盘的最新有效日期
        Date date = DateTimeUtil.getLastDate4Stock(new DateTime()).toDate();
        //TODO 使用真实数据后删除本行代码
        date = DateTime.parse("20220103145900", DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //查询数据
        List<InnerMarketDomain> innerMarketDomains = stockMarketIndexInfoMapper.selectByIdsAndDate(innerIds, date);
        //封装返回
        return R.ok(innerMarketDomains);
    }

    @Override
    public R<List<StockBlockRtInfoDomain>> sectorAllLimit() {
        List<StockBlockRtInfoDomain> stockBlockRtInfos = sbriMapper.sectorAllLimit();
        return R.ok(stockBlockRtInfos);
    }

    @Override
    public R<List<StockUpdownDomain>> stockIncreaseLimit() throws CustomerException {
        Date date = DateTimeUtil.getLastDate4Stock(new DateTime()).toDate();
        //TODO 虚拟数据 等到有真实数据后删除本行
        date = DateTime.parse("20220114150000", DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<StockUpdownDomain> stockUpdownDomains = stockRtInfoMapper.stockIncreaseLimit(date);
        if (CollectionUtils.isEmpty(stockUpdownDomains)) {
            throw new CustomerException(ResponseCode.NO_RESPONSE_DATA);
        }
        return R.ok(stockUpdownDomains);
    }

    @Override
    public R<PageResult<StockUpdownDomain>> stockPage(Integer page, Integer pageSize) throws CustomerException {
        PageHelper.startPage(page, pageSize);
        List<StockUpdownDomain> stockUpdownDomains = stockRtInfoMapper.stockAll();
        PageInfo<StockUpdownDomain> pageInfo = new PageInfo<>(stockUpdownDomains);

        if (CollectionUtils.isEmpty(pageInfo.getList())) {
            throw new CustomerException(ResponseCode.NO_RESPONSE_DATA);
        }

        PageResult<StockUpdownDomain> pageResult = new PageResult<>(pageInfo);

        return R.ok(pageResult);
    }

    @Override
    public R<Map> upDownCount() {
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(new DateTime());
        DateTime openDateTime = DateTimeUtil.getOpenDate(curDateTime);
        Date curDate = curDateTime.toDate();
        Date openDate = openDateTime.toDate();
        //TODO 模拟数据 有了真实数据后删除下面两行
        curDate = DateTime.parse("20220107145800", DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        openDate = DateTime.parse("20220107143400", DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        //查询涨停
        List<Map> upList = stockRtInfoMapper.upDownCount(curDate, openDate, 1);
        //查询跌停
        List<Map> downList = stockRtInfoMapper.upDownCount(curDate, openDate, 0);
        //封装数据返回
        HashMap<String, List<Map>> map = new HashMap<>();
        map.put("upList", upList);
        map.put("downList", downList);
        return R.ok(map);
    }

    @Override
    public void stockExport(OutputStream os, Integer page, Integer pageSize) throws CustomerException {
        PageResult<StockUpdownDomain> pageResult = stockPage(page, pageSize).getData();
        String sheetName = "page_" + page;
        EasyExcel.write(os, StockUpdownDomain.class)
                .sheet(sheetName).doWrite(pageResult.getRows());
    }

    @Override
    public R<Map> stockTradeVol4InnerMarket() {
        //获取最近的股票有效时间
        DateTime lastDate = DateTimeUtil.getLastDate4Stock(new DateTime());
        //TODO 假数据 使用真实数据后删除本行
        lastDate = DateTime.parse("2022-01-03 14:59:00",
                DateTimeFormat.forPattern(TIME_FORMAT_STR));
        //获取最近的股票有效时间 对应的开盘时间
        DateTime openDate = DateTimeUtil.getOpenDate(lastDate);
        //获取最近的股票有效时间 前一天有效时间
        DateTime yesLastDate = DateTimeUtil.getLastDate4Stock(DateTimeUtil.getPreDateTime(lastDate));
        //获取最近的股票有效时间 前一天有效时间 对应的开盘时间
        DateTime yesOpenDate = DateTimeUtil.getOpenDate(yesLastDate);
        //查询今日成交量数据
        List<Map> volList = stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(),
                openDate.toDate(), lastDate.toDate());
        //查询昨日成交量数据
        List<Map> yesVolList = stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(),
                yesOpenDate.toDate(), yesLastDate.toDate());

        //封装返回
        HashMap<String, List> map = new HashMap<>();
        map.put("volList", volList);
        map.put("yesVolList", yesVolList);
        return R.ok(map);
    }

    @Override
    public R<Map> stockUpDownScopeCount() {
        //获取最新的有效股票时间
        DateTime lastDate4Stock = DateTimeUtil.getLastDate4Stock(new DateTime());
        //TODO 假数据 使用真实数据后删除本行
        lastDate4Stock = DateTime.parse("2021-12-30 09:32:00",
                DateTimeFormat.forPattern(TIME_FORMAT_STR));
        //查询数据
        List<Map> dbMaps = stockRtInfoMapper.stockUpDownScopeCount(lastDate4Stock.toDate());

        List<Map> maps = new ArrayList<>(stockInfoConfig.getUpDownRange().size());
        //初始化
        for (String s : stockInfoConfig.getUpDownRange()) {
            HashMap<Object, Object> map = new HashMap<>();
            map.put("count", 0);
            map.put("title", s);
            maps.add(map);
        }
        for (Map dbMap : dbMaps) {
            int i = stockInfoConfig.getUpDownRange().indexOf(dbMap.get("title"));
            maps.add(i, dbMap);
        }

        //封装返回
        HashMap<String, Object> resMap = new HashMap<>();
        resMap.put("time", lastDate4Stock.toDate());
        resMap.put("infos", maps);
        return R.ok(resMap);
    }

    @Override
    public R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String code) throws CustomerException {
        if (StringUtils.isBlank(code)) {
            throw new CustomerException(ResponseCode.DATA_ERROR);
        }

        DateTime lastDate = DateTimeUtil.getLastDate4Stock(new DateTime());
        //TODO 假数据 使用真数据后删除本行
        lastDate = DateTime.parse("2022-01-06 11:15:00", DateTimeFormat.forPattern(TIME_FORMAT_STR));
        DateTime openDate = DateTimeUtil.getOpenDate(lastDate);

        List<Stock4MinuteDomain> domainList = stockRtInfoMapper.stockScreenTimeSharing(code, openDate.toDate(), lastDate.toDate());

        return R.ok(domainList);
    }

    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine(String code) throws CustomerException {
        if (StringUtils.isBlank(code)) {
            throw new CustomerException(ResponseCode.DATA_ERROR);
        }

        DateTime lastDate = DateTimeUtil.getLastDate4Stock(new DateTime());
        //TODO 假数据 使用真数据后删除
        lastDate = DateTime.parse("2022-01-06 11:15:00", DateTimeFormat.forPattern(TIME_FORMAT_STR));
        DateTime openDate = DateTimeUtil.getOpenDate(lastDate);
        openDate = openDate.minusDays(20);

        List<Stock4EvrDayDomain> domains = stockRtInfoMapper.stockCreenDkLine(code, openDate.toDate(), lastDate.toDate());

        return R.ok(domains);
    }
}
